/*******************************************************************************
 * Copyright (c) 2011 Jerry Zhang & Eva Xie.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of GPL 2.0
 * 
 * Contributors:
 *     Jerry Zhang, Eva Xie.
 *******************************************************************************/
package com.alienwarp.gui;

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;

import com.alienwarp.imageprocess.ImageProcessor;

public class MainFrame
{
	static String AppName = "AlienWarp";
	Display display; 
	static Shell shell;
	String strLastFilePath = null; // Used to seed the last file path, updated
									// everytime the user open a image file.
	ImageData imgData; // store the image data that user open.

	static final String[] OPEN_FILTER_EXTENSIONS = new String[] {
			"*.bmp; *.gif; *.ico; *.jfif; *.jpeg; *.jpg; *.png; *.tif; *.tiff",
			"*.bmp", "*.gif", "*.ico", "*.jpg; *.jpeg; *.jfif", "*.png",
			"*.tif; *.tiff" };
	static final String[] OPEN_FILTER_NAMES = new String[] {
			"All_images" + " (bmp, gif, ico, jfif, jpeg, jpg, png, tif, tiff)",
			"BMP (*.bmp)", "GIF (*.gif)", "ICO (*.ico)",
			"JPEG (*.jpg, *.jpeg, *.jfif)", "PNG (*.png)",
			"TIFF (*.tif, *.tiff)" };

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		// TODO Auto-generated method stub
		Display display = new Display();
		MainFrame frame = new MainFrame();
		frame.initialInstance(display);

		while (!shell.isDisposed())
		{
			if (!display.readAndDispatch())
				display.sleep();
		}

		display.dispose();
	}

	/*
	 * Initialize the application 1)Create the shell 2)Setup the menu bar
	 */

	public Shell initialInstance(Display display)
	{
		this.display = display;
		shell = new Shell(display);
		shell.setText(AppName);

		shell.addPaintListener(new PaintListener()
		{
			@Override
			public void paintControl(PaintEvent event)
			{
				if (null == imgData)
				{
					Rectangle bounds = shell.getClientArea();
					event.gc.drawRectangle(bounds);
				} else
				{
					paintImage(event);
				}
			}
		});

		createMenuBar();

		// All the initialization have been done, Open the main window.
		shell.open();
		return shell;
	}

	/*
	 * Create the menu bars, including: 1)Main menu;
	 */
	Menu createMenuBar()
	{
		// Menu bar.
		Menu menuBar = new Menu(shell, SWT.BAR);
		shell.setMenuBar(menuBar);
		createFileMenu(menuBar);
		createImageProcessMenu(menuBar);
		return menuBar;
	}

	void createFileMenu(Menu menuBar)
	{
		// File menu
		MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
		item.setText("File");
		Menu fileMenu = new Menu(shell, SWT.DROP_DOWN);
		item.setMenu(fileMenu);

		// File -> Open File...
		item = new MenuItem(fileMenu, SWT.PUSH);
		item.setText("&OpenFile");
		item.setAccelerator(SWT.MOD1 + 'O');
		item.addSelectionListener(new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent event)
			{
				menuOpenFile();
			}
		});

		// File -> Exit
		item = new MenuItem(fileMenu, SWT.PUSH);
		item.setText("Exit");
		item.addSelectionListener(new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent event)
			{
				shell.close();
			}
		});
	} // end of void createFileMenu(Menu menuBar)
	
	void createImageProcessMenu(Menu menuBar)
	{
		//Image Process Menu
		MenuItem item = new MenuItem(menuBar, SWT.CASCADE);
		item.setText("Image Process");
		Menu imageProcessMenu = new Menu(shell, SWT.DROP_DOWN);
		item.setMenu(imageProcessMenu);

		// File -> Open File...
		item = new MenuItem(imageProcessMenu, SWT.PUSH);
		item.setText("&Mean Filter");
		item.setAccelerator(SWT.MOD1 + 'M');
		item.addSelectionListener(new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent event)
			{
				onImageMeanFilter();
			}
		});
	}//end of void createImageProcessingMenu(Menu menuBar)

	/*
	 * This function is called when user clicked "File"->"Open File" menu item.
	 * This function first display a file open dialog for the user to choose a
	 * valid image file.
	 */
	void menuOpenFile()
	{
		// Get the user to choose an image file.
		FileDialog fileChooser = new FileDialog(shell, SWT.OPEN);
		if (strLastFilePath != null)
			fileChooser.setFilterPath(strLastFilePath);
		fileChooser.setFilterExtensions(OPEN_FILTER_EXTENSIONS);
		fileChooser.setFilterNames(OPEN_FILTER_NAMES);
		String filename = fileChooser.open();
		strLastFilePath = fileChooser.getFilterPath();
		if (filename == null)
			return;

		Cursor waitCursor = display.getSystemCursor(SWT.CURSOR_WAIT);
		shell.setCursor(waitCursor);
		try
		{
			imgData = new ImageData(filename);
		} catch (SWTException e)
		{
			imgData = null;
		} finally
		{
			shell.setCursor(null);
		}

		shell.redraw();

	}// end of void menuOpenFile()
	
	/*
	 * Called when "image process" --> "Mean Filter" pressed.
	 */
	void onImageMeanFilter()
	{
		ImageData newImageData = ImageProcessor.imageMeanFilter(imgData, 3, 3);
		imgData = newImageData;
		shell.redraw();
	}

	/*
	 * Called when image has been opened and need to be redraw.
	 */
	void paintImage(PaintEvent event)
	{
		Image imageDisplay;
		GC gc = event.gc;

		try
		{
			imageDisplay = new Image(display, imgData);
		} catch (SWTException e)
		{
			imageDisplay = null;
		}

		Rectangle clientRect = shell.getClientArea();
		float ratioX = 1.0f, ratioY = 1.0f;
		if (imgData.width > clientRect.width)
		{
			ratioX = (float) imgData.width / clientRect.width;
		}
		if (imgData.height > clientRect.height)
		{
			ratioY = (float) imgData.height / clientRect.height;
		}

		float ratio = ratioX > ratioY ? ratioX : ratioY;

		int left, top, width, height;
		//positioning the image to center of the client area. shrink the image if needed.
		left = (int) ((clientRect.width - imgData.width / ratio) / 2);
		top = (int) ((clientRect.height - imgData.height / ratio) / 2);
		width = (int) (imgData.width / ratio);
		height = (int) (imgData.height / ratio);

		gc.drawImage(imageDisplay, 0, 0, imgData.width, imgData.height, left,
				top, width, height);

		/* Image should be dispose because it uses the system resource. */
		if (null != imageDisplay)
		{
			imageDisplay.dispose();
		}
	}// end of void displayImage()
}
